package com.audaque.springboot.foshanupload.redis.component;

import com.audaque.springboot.foshanupload.core.exception.RetryMaxException;
import com.audaque.springboot.foshanupload.core.exception.RetryingException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.RedisScript;
import com.audaque.springboot.foshanupload.core.exception.RetryingException;
import org.springframework.retry.annotation.Backoff;
import org.springframework.retry.annotation.Recover;
import org.springframework.retry.annotation.Retryable;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @author zgb
 * @desc ...
 * @date 2022-01-12 16:01:33
 */
@Slf4j
@Component
public class StringRedisTemplateRetry {
    /**
     * 注入redis操作类
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Recover
    public void recover(RetryingException e) throws RetryMaxException {
        String message = e.getMessage();
        String r =  "重试次数已达上限:"+message;
        log.warn(r);
        //不要使用Exception，否则自定义异常信息丢失，要使用自定义 RetryMaxException extends RuntimeException
        throw new RetryMaxException(r);
    }

    //retry不能有返回值,retry代替while或递归，调用者不要catch RetryException否则会把Exception抓住，导致Exception丢失
    @Retryable(value = RetryingException.class, maxAttempts = Integer.MAX_VALUE, backoff = @Backoff(value =  5* 1000,maxDelay = 1*60 * 1000,  multiplier = 1.1))
    public  void execute(RedisScript<List> script, List<String> keys, Object... args)  throws RetryMaxException  {
        List result = stringRedisTemplate.execute(script, keys, args);
        result=ListUtils.emptyIfNull(result);
        Object o = result.get(0);
        String s = o.toString();
        //lua 脚本返回 "0" 表示超出流量大小，返回1表示没有超出流量大小
        if(StringUtils.equals(s,"0")){
            String msg="lua 脚本返回 '0' 表示超出流量大小";
            log.warn(msg);
            throw new RetryingException(msg);

        }
    }

}
